package cn.com.cifi.mars.service.impl;
import cn.com.cifi.mars.bean.bo.returnPlan.ReturnPlanMySaleDataBO;
import cn.com.cifi.mars.bean.bo.returnPlan.ReturnPlanNosSaleDataBO;
import cn.com.cifi.mars.bean.bo.returnPlan.ReturnPlanSaleDataBO;
import cn.com.cifi.mars.bean.dto.MymContractDto;
import cn.com.cifi.mars.bean.dto.NosTradedataDto;
import cn.com.cifi.mars.bean.dto.VsMarsFeeDto;
import cn.com.cifi.mars.bean.dto.returnPlan.ReturnSignMyReceiptsDto;
import cn.com.cifi.mars.bean.dto.returnPlan.ReturnSignNosReceiptsDto;
import cn.com.cifi.mars.bean.dto.returnPlan.ReturnSignReceivableDto;
import cn.com.cifi.mars.bean.dto.returnPlan.ReturnSignRecordsDto;
import cn.com.cifi.mars.bean.vo.returnPlan.ReturnPlanGroupVo;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.*;
import cn.com.cifi.mars.entity.*;
import cn.com.cifi.mars.mapper.mars.*;
import cn.com.cifi.mars.mapper.wrapper.ReturnPlanVersionDetailWrapper;
import cn.com.cifi.mars.service.*;
import cn.com.cifi.mars.util.*;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 回款计划版本明细表 服务实现类
 * </p>
 *
 * @author JingYuanXiang
 * @since 2020-11-06
 */
@Slf4j
@Service
public class ReturnPlanVersionDetailServiceImpl extends ServiceImpl<ReturnPlanVersionDetailMapper, ReturnPlanVersionDetail> implements ReturnPlanVersionDetailService {

    @Autowired
    private ReturnPlanVersionDetailMapper returnPlanVersionDetailMapper;
    @Autowired
    private ReturnPlanVersionDetailWrapper returnPlanVersionDetailWrapper;
    @Autowired
    private SignPlanVersionDetailMapper signPlanVersionDetailMapper;
    @Autowired
    private SignPlanVersionSupplyDetailMapper signPlanVersionSupplyDetailMapper;
    @Autowired
    private ReturnPlanVersionCoefficientService returnPlanVersionCoefficientService;
    @Autowired
    private DmOdsMyVsMarsSContractService dmOdsMyVsMarsSContractService;
    @Autowired
    private VsMarsFeeService vsMarsFeeService;
    @Autowired
    private VsMarsGetinService vsMarsGetinService;
    @Autowired
    private DmOdsNosTradedataviewformarsService dmOdsNosTradedataviewformarsService;
    @Autowired
    private VsNosPayabledataviewformarsService vsNosPayabledataviewformarsService;
    @Autowired
    private DmMyReturnAmountMapper dmMyReturnAmountMapper;
    @Autowired
    private VsMarsGetinzclService vsMarsGetinzclService;
    @Autowired
    private StageService stageService;

    /**
     * 创建回款计划详情列表
     * @param returnPlanVersion 回款计划版本
     */
    @Override
    public void createList(ReturnPlanVersion returnPlanVersion) {
        //回款计划详情列表
        List<ReturnPlanVersionDetail> returnPlanVersionDetailList = new ArrayList<>();
        //取数来源
        String dataSource = returnPlanVersion.getDataSource();
        if(VersionTypeEunm.INVESTMENT.getKey().equals(returnPlanVersion.getVersionType())){
            //初始化生成回款计划详情列表
            returnPlanVersionDetailList = initializeList(returnPlanVersion,new ReturnPlanSaleDataBO());
            //计算投资版回款计划详情数据
            calculateListByInvestment(returnPlanVersion,returnPlanVersionDetailList);
        }else if(FetchNnumberEnum.MY.getKey().equals(dataSource)){
            //获取回款明源签约数据
            ReturnPlanMySaleDataBO returnSignDataBO = getReturnMySignData(returnPlanVersion);
            //初始化生成回款计划详情列表
            returnPlanVersionDetailList = initializeList(returnPlanVersion, returnSignDataBO);
            //计算回款计划详情数据
            calculateListByMy(returnPlanVersion,returnPlanVersionDetailList,returnSignDataBO);
        }else if(FetchNnumberEnum.NOS.getKey().equals(dataSource)){
            //获取回款NOS签约数据
            ReturnPlanNosSaleDataBO returnSignDataBO = getReturnNosSignData(returnPlanVersion);
            //初始化生成回款计划详情列表
            returnPlanVersionDetailList = initializeList(returnPlanVersion, returnSignDataBO);
            //计算回款计划详情数据
            calculateListByNos(returnPlanVersion,returnPlanVersionDetailList,returnSignDataBO);
        }else {
            throw new MsgException(CodeEnum.SYS_PROJECT_FETCH_ERROR);
        }
        returnPlanVersionDetailMapper.insertList(returnPlanVersionDetailList);
    }


    /**
     * 获取回款计划详情列表
     * @param versionId 版本id
     * @param groupId 组团id
     * @return
     */
    @Override
    public List<ReturnPlanVersionDetail> getListByVersionIdAndgroupId(String versionId, String groupId) {
        return returnPlanVersionDetailWrapper.selectByVersionIdAndGroupId(versionId,groupId,IsDeleteEnum.NO.getKey());
    }

    /**
     * 编辑保存
     * @param detailList 回款计划详情列表
     */
    @Override
    public void editSave(List<ReturnPlanVersionDetail> detailList) {
        //期末应收
        BigDecimal finalReceivable = BigDecimal.ZERO;

        for(ReturnPlanVersionDetail detail : detailList){
            detail.setId(UUIDUtils.create());
            finalReceivable = finalReceivable.add(detail.getSignAmount()).subtract(detail.getTotalReturnAmount());
        }

        //是否编制完成
        int isEstablishment;

        BigDecimal hundred = new BigDecimal(100);
        if(finalReceivable.abs().compareTo(hundred) <= 0){
            isEstablishment =  WhetherEnum.YES.getKey();
        }else {
            isEstablishment =  WhetherEnum.NO.getKey();
        }
        //赋值是否已编制完成
        detailList.forEach(s->s.setIsEstablishment(isEstablishment));
        //保存
        returnPlanVersionDetailMapper.insertList(detailList);
    }

    /**
     * 获取回款计划编辑页面组团列表
     * @param versionId 回款计划版本id
     * @return
     */
    @Override
    public List<ReturnPlanGroupVo> getGroupList(String versionId) {
        return returnPlanVersionDetailMapper.selectReturnPlanGroupVoList(versionId,IsDeleteEnum.NO.getKey());
    }

    /**
     * 年月回款合计
     * @param yearMonth 年月
     * @param returnPlanVersionDetailList 回款计划详情列表
     * @return
     */
    @Override
    public BigDecimal getTotalReturnAmountByYearMonth(String yearMonth, List<ReturnPlanVersionDetail> returnPlanVersionDetailList) {
        if(CollectionUtils.isEmpty(returnPlanVersionDetailList)){
            return BigDecimal.ZERO;
        }
        return returnPlanVersionDetailList.stream()
                .filter(s -> yearMonth.equals(LocalDateTimeUtils.formatTime(s.getReturnTime(), DateUtils.DATE_JFP_STR)))
                .map(ReturnPlanVersionDetail::getTotalReturnAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 当年回款合计
     * @param year 年
     * @param returnPlanVersionDetailList 回款计划详情列表
     * @return
     */
    @Override
    public BigDecimal getTotalReturnAmountByYear(String year, List<ReturnPlanVersionDetail> returnPlanVersionDetailList) {
        if(CollectionUtils.isEmpty(returnPlanVersionDetailList)){
            return BigDecimal.ZERO;
        }
        return returnPlanVersionDetailList.stream()
                .filter(s -> year.equals(String.valueOf(s.getReturnTime().getYear())))
                .map(ReturnPlanVersionDetail::getTotalReturnAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取最末月的期末应收
     * @param returnPlanVersionDetailList 回款计划详情列表
     * @return
     */
    @Override
    public BigDecimal getLastMonthFinalReceivable(List<ReturnPlanVersionDetail> returnPlanVersionDetailList) {
        if(CollectionUtils.isEmpty(returnPlanVersionDetailList)){
            return BigDecimal.ZERO;
        }
        ReturnPlanVersionDetail detail = returnPlanVersionDetailList.stream()
                .max(Comparator.comparing(ReturnPlanVersionDetail::getReturnTime))
                .orElse(null);
        if(null == detail){
            return BigDecimal.ZERO;
        }else {
            return detail.getFinalReceivable();
        }
    }

    /**
     * 逻辑删除指定组团回款计划详情
     * @param versionId 组团id
     * @param groupId 组团id
     * @param alias 组团id
     */
    @Override
    public void delByGroupId(String versionId, String groupId, String alias) {
        returnPlanVersionDetailMapper.delByGroupId(versionId,groupId,alias,IsDeleteEnum.YES.getKey());
    }

    /**
     * 基于明源签约数据计算回款计划详情数据
     * @param returnPlanVersion 回款计划版本
     * @param returnPlanVersionDetailList 回款计划详情列表
     * @param returnSignDataBO
     */
    private void calculateListByMy(ReturnPlanVersion returnPlanVersion, List<ReturnPlanVersionDetail> returnPlanVersionDetailList, ReturnPlanMySaleDataBO returnSignDataBO) {
        //获取回款系数数据（计算当月及未来月数据使用）(key:标准业态编码，(key:月数，value:回款系数)
        Map<String,Map<Integer,BigDecimal>> returnCoefficientMap = getReturnCoefficientData(returnPlanVersion);

        //以组团id和组合业态分组，并已回款时间做升序排序,(key:组团ID，(key:组合业态编码，value:回款计划详情))
        Map<String, LinkedHashMap<String, List<ReturnPlanVersionDetail>>> returnPlanDetailByGroupIdMap = returnPlanVersionDetailList
                .stream().sorted(Comparator.comparing(ReturnPlanVersionDetail::getReturnTime))
                .collect(Collectors.groupingBy(ReturnPlanVersionDetail::getGroupId,
                        Collectors.groupingBy(ReturnPlanVersionDetail::getCombinationProductCode, LinkedHashMap::new, Collectors.toList())));

        for (String groupId : returnPlanDetailByGroupIdMap.keySet()) {
            LinkedHashMap<String, List<ReturnPlanVersionDetail>> returnPlanDetailMap = returnPlanDetailByGroupIdMap.get(groupId);
            for (String combinationProductCode : returnPlanDetailMap.keySet()) {
                //累计签约合同id列表
                List<String> cumulativeSignRoomIdList = new ArrayList();
                //上月应收未收
                BigDecimal lastMonthNotReceivableAmount = BigDecimal.ZERO;
                //应收未收
                BigDecimal notReceivableAmount = BigDecimal.ZERO;
                //期初应收
                BigDecimal earlyReceivableAmount = BigDecimal.ZERO;
                //累计回款合计
                BigDecimal returnAmountTotal = BigDecimal.ZERO;
                //累计年度签约合计
                BigDecimal yearSignAmountTotal = BigDecimal.ZERO;
                //累计年度回款合计
                BigDecimal yearReturnAmountTotal = BigDecimal.ZERO;
                //累计签约合计
                BigDecimal signAmountTotal = BigDecimal.ZERO;
                //1月期初应收
                BigDecimal beginningReceivable = BigDecimal.ZERO;

                List<ReturnPlanVersionDetail> returnPlanDetails = returnPlanDetailMap.get(combinationProductCode);
                //获取签约金额Map(key:年月,value:签约金额)
                Map<String, BigDecimal> contractAmountMap = returnPlanDetails.stream()
                        .collect(Collectors.toMap(s -> LocalDateTimeUtils.formatTime(s.getReturnTime(), DateUtils.DATE_JFP_STR), ReturnPlanVersionDetail::getSignAmount));

                for (ReturnPlanVersionDetail returnPlanDetail : returnPlanDetails){
                    String yearMonth =  LocalDateTimeUtils.formatTime(returnPlanDetail.getReturnTime(), DateUtils.DATE_JFP_STR);

                    //获取当月应收
                    BigDecimal receivableAmount = returnSignDataBO.getReceivableMoneyByEQYearMonth(groupId,combinationProductCode,yearMonth);
                    //获取当月实收
                    BigDecimal receiptsAmount = returnSignDataBO.getReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                    //应收未收
                    notReceivableAmount = receivableAmount.subtract(receiptsAmount);
                    //是否当年1月(重新计算累计年度回款合计、累计年度签约合计、1月期初应收)
                    if(returnPlanDetail.getReturnTime().getMonthValue() == 1){
                        yearReturnAmountTotal = BigDecimal.ZERO;
                        yearSignAmountTotal = BigDecimal.ZERO;
                        beginningReceivable = earlyReceivableAmount;
                    }
                    //是否历史月
                    if(LocalDateTimeUtils.compareDate(returnPlanDetail.getReturnTime(),returnPlanVersion.getCreateTime(),0)){
                        //获取当月签约的合同id列表在小于等于当月实收的金额
                        BigDecimal incrementReturnAmountActual = returnSignDataBO.getZlReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //获取累计签约合同id列表在等于当月实收的金额
                        BigDecimal storeReturnAmountActual = returnSignDataBO.getClReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //筛选指定合同id列表中当月及以前的实收大于当月及以前的应收的合同id列表,获取其中当月及以前的实收大于当月及以前的应收的金额合计
                        BigDecimal refundable = returnSignDataBO.getRefundable(groupId,combinationProductCode,yearMonth);

                        //实际数-增量回款(当月签约的合同在当月及以前月实收的金额)
                        returnPlanDetail.setIncrementReturnAmountActual(incrementReturnAmountActual);
                        //实际数-存量回款(当月之前签约的合同在当月实收的金额)
                        returnPlanDetail.setStoreReturnAmountActual(storeReturnAmountActual);
                        //期初应退回款数(当月及以前签约的合同中当月及以前实收大于当月及以前应收的金额合计)
                        returnPlanDetail.setRefundable(refundable);
                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(receivableAmount);
                        //增量回款-本期回款数(历史月：实际数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountActual());
                        //存量回款-本期回款数(历史月：实际数-存量回款)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountActual());
                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                        //获取下个月的上月应收未收（应收未收）
                        lastMonthNotReceivableAmount = lastMonthNotReceivableAmount.add(notReceivableAmount);
                        //是否编制月
                    }else if(LocalDateTimeUtils.compareDate(returnPlanDetail.getReturnTime(),returnPlanVersion.getCreateTime(),2)){
                        //获取当月签约的合同id列表在小于等于当月实收的金额
                        BigDecimal incrementReturnAmountActual = returnSignDataBO.getZlReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //获取累计签约合同id列表在等于当月实收的金额
                        BigDecimal storeReturnAmountActual = returnSignDataBO.getClReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //筛选指定合同id列表中当月及以前的实收大于当月及以前的应收的合同id列表,获取其中当月及以前的实收大于当月及以前的应收的金额合计
                        BigDecimal refundable = returnSignDataBO.getRefundable(groupId,combinationProductCode,yearMonth);

                        //第1个月回款系数
                        BigDecimal oneMonthCoefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(1);
                        //当月签约 * 第1个月回款系数
                        BigDecimal incrementReturnAmountCalculate = returnPlanDetail.getPlanSignAmount().multiply(oneMonthCoefficient).setScale(5, BigDecimal.ROUND_HALF_UP);;
                        //实际数-增量回款(当月签约的合同在当月及以前月实收的金额)
                        returnPlanDetail.setIncrementReturnAmountActual(incrementReturnAmountActual);
                        //实际数-存量回款(当月之前签约的合同在当月实收的金额)
                        returnPlanDetail.setStoreReturnAmountActual(storeReturnAmountActual);
                        //期初应退回款数(当月及以前签约的合同中当月及以前实收大于当月及以前应收的金额合计)
                        returnPlanDetail.setRefundable(refundable);
                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(receivableAmount);
                        //增量回款-测算数(当月签约 * 第1个月回款系数)
                        returnPlanDetail.setIncrementReturnAmountCalculate(incrementReturnAmountCalculate);
                        //存量回款-测算数(编制月为0)(从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和)
                        returnPlanDetail.setStoreReturnAmountCalculate(BigDecimal.ZERO);
                        //增量回款-本期回款数(当月：测算数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountCalculate());
                        //存量回款-本期回款数(当月：测算数-存量回款 + 上月应收未收 + 当月应收)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountCalculate()
                                .add(lastMonthNotReceivableAmount).add(returnPlanDetail.getReceivableAmount()));

                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                        //获取下个月的上月应收未收（应收未收）
                        lastMonthNotReceivableAmount = BigDecimal.ZERO;

                        //是否未来月
                    }else {
                        //第1个月回款系数
                        BigDecimal oneMonthCoefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(1);
                        //当月签约 * 第1个月回款系数
                        BigDecimal incrementReturnAmountCalculate = returnPlanDetail.getPlanSignAmount().multiply(oneMonthCoefficient);
                        //从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和
                        BigDecimal storeReturnAmountCalculate = BigDecimal.ZERO;
                        for (LocalDateTime time = returnPlanVersion.getCreateTime(); LocalDateTimeUtils.compareDate(time, returnPlanDetail.getReturnTime(), 0); time = LocalDateTimeUtils.addDate(time)) {
                            //签约金额
                            BigDecimal contractAmount = contractAmountMap.get(LocalDateTimeUtils.formatTime(time, DateUtils.DATE_JFP_STR));
                            //月数
                            int monthCount = LocalDateTimeUtils.monthDiff(time, returnPlanDetail.getReturnTime()) + 1;
                            //回款系数
                            BigDecimal coefficient;
                            if(monthCount > 24){
                                //回款系数
                                coefficient = BigDecimal.ZERO;
                            }else {
                                //回款系数
                                coefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(monthCount);
                            }
                            //回款金额
                            BigDecimal returnAmount = contractAmount.multiply(coefficient);

                            storeReturnAmountCalculate = storeReturnAmountCalculate.add(returnAmount);
                        }

                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(receivableAmount);
                        //增量回款-测算数(当月签约 * 第1个月回款系数)
                        returnPlanDetail.setIncrementReturnAmountCalculate(incrementReturnAmountCalculate);
                        //存量回款-测算数(从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和)
                        returnPlanDetail.setStoreReturnAmountCalculate(storeReturnAmountCalculate);
                        //增量回款-本期回款数(未来月：测算数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountCalculate());
                        //存量回款-本期回款数(未来月：测算数-存量回款  +  上月应收未收 + 当月应收)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountCalculate()
                                .add(lastMonthNotReceivableAmount).add(returnPlanDetail.getReceivableAmount()));

                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                    }
                    //累计签约合计(历史月累加实际签约,的编制月及未来月累加计划签约)
                    signAmountTotal = signAmountTotal.add(returnPlanDetail.getSignAmount());
                    //累计年度签约合计(历史月累加实际签约,的编制月及未来月累加计划签约)
                    yearSignAmountTotal = yearSignAmountTotal.add(returnPlanDetail.getSignAmount());
                    //累计回款合计(累计回款合计 + 当月回款合计)
                    returnAmountTotal = returnAmountTotal.add(returnPlanDetail.getTotalReturnAmount());
                    //累计年度回款合计(累计年度回款合计 + 当月回款合计)
                    yearReturnAmountTotal = yearReturnAmountTotal.add(returnPlanDetail.getTotalReturnAmount());
                    //累计签约回款率(开售月累计到当月回款合计/开售月累计到累计当月签约金额)
                    BigDecimal signReturnRate = BigDecimalUtils.divBigDecimal(returnAmountTotal,signAmountTotal,5);
                    //年度综合回款率(从当年1月累计到当月回款合计/(当年1月的期初应收 + 从当年1月累计到累计当月签约金额)
                    BigDecimal annualOverallReturnRate = BigDecimalUtils
                            .divBigDecimal(yearReturnAmountTotal,beginningReceivable.add(yearSignAmountTotal),5);

                    returnPlanDetail.setYearReturnAmountTotal(yearReturnAmountTotal);
                    returnPlanDetail.setReturnAmountTotal(returnAmountTotal);
                    returnPlanDetail.setYearSignAmountTotal(yearSignAmountTotal);
                    returnPlanDetail.setSignAmountTotal(signAmountTotal);
                    returnPlanDetail.setSignReturnRate(signReturnRate);
                    returnPlanDetail.setAnnualOverallReturnRate(annualOverallReturnRate);
                }
            }
        }
    }

    /**
     * 获取供款计划
     * @param returnPlanVersion 分期id
     */
    private ReturnPlanMySaleDataBO getReturnMySignData(ReturnPlanVersion returnPlanVersion) {
        ReturnPlanMySaleDataBO installmentDataBO = new ReturnPlanMySaleDataBO();

        //查询分期数据
        MdmStage mdmStage = stageService.selectById(returnPlanVersion.getStageId());
        //产品构成层级供货详情列表
        List<SignPlanVersionSupplyDetail> supplyDetailList = signPlanVersionSupplyDetailMapper.selectByVersionIds(Arrays.asList(returnPlanVersion.getSignPlanVersionId()), IsDeleteEnum.NO.getKey());
        //获取组团idMap(key:供货id,value:组团id)
        Map<String, String> groupIdMap = supplyDetailList.stream()
                .filter(s -> OrgTypeEunm.ORG_GROUP.getKey().equals(s.getType()))
                .collect(Collectors.toMap(SignPlanVersionSupplyDetail::getSupplyPlanId, SignPlanVersionSupplyDetail::getOrgId));
        //获取组团idMap(key:楼栋id,value:组团id)
        Map<String, String> groupIdByBuildingMap = supplyDetailList.stream()
                .filter(s -> OrgTypeEunm.ORG_PRODUCT.getKey().equals(s.getType()))
                .collect(Collectors.toMap(SignPlanVersionSupplyDetail::getOrgId, s -> groupIdMap.get(s.getPid())));
        //获取楼栋id与组合业态关系Map(key:楼栋id,value:组合业态)
        Map<String,String> buildingMap = supplyDetailList.stream()
                .filter(s -> OrgTypeEunm.ORG_PRODUCT.getKey().equals(s.getType()) && StringUtils.isNotBlank(s.getOrgId()))
                .collect(Collectors.toMap(SignPlanVersionSupplyDetail::getOrgId,s -> s.getOrgCode() +s.getFreeType() +s.getBusinessType() +s.getProType()));

        List<String> buildingList = new ArrayList<>(buildingMap.keySet());

        if(CollectionUtils.isEmpty(buildingList)){
            return installmentDataBO;
        }

        //签约记录(签约合同记录表)
        List<MymContractDto> mymContractDtos = dmOdsMyVsMarsSContractService.selectMymContractList(new ArrayList<>(buildingMap.keySet()));
        //应收
        List<VsMarsFeeDto> vsMarsFeeDtoList = vsMarsFeeService.selectByStageId(returnPlanVersion.getStageId());
        //交易实收
        List<VsMarsGetinzcl> vsMarsGetinzclList = vsMarsGetinzclService.selectByKingdeeProjectfId(mdmStage.getKingdeeProjectfId());

        //当前年月之前退房合同id列表
        List<String> closeContractGUIDList = mymContractDtos.stream()
                .filter(s -> null != s.getCloseDate() && LocalDateTimeUtils.compareDate(s.getCloseDate(), LocalDateTime.now(), 0))
                .map(s -> s.getContractGUID())
                .collect(Collectors.toList());
        //获取交易id月合同id映射关系
        Map<String, String> contractGUIDMap = mymContractDtos.stream().collect(Collectors.toMap(s -> s.getTradeGUID(), s -> s.getContractGUID()));
        //获取合同id月楼栋id映射关系
        Map<String, String> bldPrdIDMap = mymContractDtos.stream().collect(Collectors.toMap(s -> s.getContractGUID(), s -> s.getBldPrdID()));

        //签约记录列表
        List<ReturnSignRecordsDto> returnSignRecordsList = mymContractDtos.stream()
            .filter(s-> LocalDateTimeUtils.compareDate(s.getYwgsDate(),LocalDateTime.now(),0))
            .map(s->{
                return new ReturnSignRecordsDto(
                    groupIdByBuildingMap.get(s.getBldPrdID()),
                    buildingMap.get(s.getBldPrdID()),
                    LocalDateTimeUtils.formatTime(s.getYwgsDate(), DateUtils.DATE_JFP_STR),
                    s.getRoomGUID(),
                    s.getContractGUID(),
                    s.getAuditDate() == null ? s.getCjRmbTotal() : s.getCjRmbTotal().add(s.getBcTotal())
                );
            }).collect(Collectors.toList());
        //应收列表
        List<ReturnSignReceivableDto> returnSignReceivableList = vsMarsFeeDtoList.stream()
            .filter(s-> !closeContractGUIDList.contains(s.getContractGUID()))
            .map(s->{
                return new ReturnSignReceivableDto(
                    groupIdByBuildingMap.get(s.getBldPrdID()),
                    s.getProductCode().replace(".",""),
                    LocalDateTimeUtils.formatTime(s.getReceiptDate(), DateUtils.DATE_JFP_STR),
                    s.getRoomId(),
                    s.getContractGUID(),
                    s.getReceiptAmount());
        }).collect(Collectors.toList());
        //实收列表
        List<ReturnSignMyReceiptsDto> returnSignReceiptsList = vsMarsGetinzclList.stream()
            .map(s->{
                return new ReturnSignMyReceiptsDto(
                    groupIdByBuildingMap.get(bldPrdIDMap.get(contractGUIDMap.get(s.getSaleGUID()))),
                    buildingMap.get(bldPrdIDMap.get(contractGUIDMap.get(s.getSaleGUID()))),
                    LocalDateTimeUtils.formatTime(s.getGetDate(), DateUtils.DATE_JFP_STR),
                    contractGUIDMap.get(s.getSaleGUID()),
                    s.getRmbAmount(),s.getZlAmount().compareTo(BigDecimal.ZERO) == 0 ? "存量" : "增量");
        }).collect(Collectors.toList());

        installmentDataBO.setReturnSignRecordsList(returnSignRecordsList);
        installmentDataBO.setReturnSignReceivableList(returnSignReceivableList);
        installmentDataBO.setReturnSignReceiptsList(returnSignReceiptsList);

        installmentDataBO.initializeMap();
        return installmentDataBO;
    }

    /**
     * 基于NOS签约数据计算回款计划详情数据
     * @param returnPlanVersion 回款计划版本
     * @param returnPlanVersionDetailList 回款计划详情列表
     * @param returnSignDataBO
     */
    private void calculateListByNos(ReturnPlanVersion returnPlanVersion, List<ReturnPlanVersionDetail> returnPlanVersionDetailList, ReturnPlanNosSaleDataBO returnSignDataBO) {
        //获取回款系数数据（计算当月及未来月数据使用）(key:标准业态编码，(key:月数，value:回款系数)
        Map<String,Map<Integer,BigDecimal>> returnCoefficientMap = getReturnCoefficientData(returnPlanVersion);

        //以组团id和组合业态分组，并已回款时间做升序排序,(key:组团ID，(key:组合业态编码，value:回款计划详情))
        Map<String, LinkedHashMap<String, List<ReturnPlanVersionDetail>>> returnPlanDetailByGroupIdMap = returnPlanVersionDetailList
                .stream().sorted(Comparator.comparing(ReturnPlanVersionDetail::getReturnTime))
                .collect(Collectors.groupingBy(ReturnPlanVersionDetail::getGroupId,
                        Collectors.groupingBy(ReturnPlanVersionDetail::getCombinationProductCode, LinkedHashMap::new, Collectors.toList())));

        for (String groupId : returnPlanDetailByGroupIdMap.keySet()) {
            LinkedHashMap<String, List<ReturnPlanVersionDetail>> returnPlanDetailMap = returnPlanDetailByGroupIdMap.get(groupId);
            for (String combinationProductCode : returnPlanDetailMap.keySet()) {
                //累计签约房间id列表
                List<String> cumulativeSignRoomIdList = new ArrayList();
                //当月应收未收
                BigDecimal currentMonthSignedUnrecovered = BigDecimal.ZERO;
                //上月应收未收
                BigDecimal lastMonthNotReceivableAmount = BigDecimal.ZERO;
                //应收未收
                BigDecimal notReceivableAmount = BigDecimal.ZERO;
                //期初应收
                BigDecimal earlyReceivableAmount = BigDecimal.ZERO;
                //累计回款合计
                BigDecimal returnAmountTotal = BigDecimal.ZERO;
                //累计年度签约合计
                BigDecimal yearSignAmountTotal = BigDecimal.ZERO;
                //累计年度回款合计
                BigDecimal yearReturnAmountTotal = BigDecimal.ZERO;
                //累计签约合计
                BigDecimal signAmountTotal = BigDecimal.ZERO;
                //1月期初应收
                BigDecimal beginningReceivable = BigDecimal.ZERO;

                List<ReturnPlanVersionDetail> returnPlanDetails = returnPlanDetailMap.get(combinationProductCode);
                //获取签约金额Map(key:年月,value:签约金额)
                Map<String, BigDecimal> contractAmountMap = returnPlanDetails.stream()
                        .collect(Collectors.toMap(s -> LocalDateTimeUtils.formatTime(s.getReturnTime(), DateUtils.DATE_JFP_STR), ReturnPlanVersionDetail::getSignAmount));
                for (ReturnPlanVersionDetail returnPlanDetail : returnPlanDetails){
                    String yearMonth =  LocalDateTimeUtils.formatTime(returnPlanDetail.getReturnTime(), DateUtils.DATE_JFP_STR);

                    //获取当月签约
                    BigDecimal signAmount = contractAmountMap.get(yearMonth);
                    //获取当月实收
                    BigDecimal receiptsAmount = returnSignDataBO.getReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                    //应收未收
                    notReceivableAmount = signAmount.subtract(receiptsAmount);

                    //是否当年1月(重新计算累计年度回款合计、累计年度签约合计、1月期初应收)
                    if(returnPlanDetail.getReturnTime().getMonthValue() == 1){
                        yearReturnAmountTotal = BigDecimal.ZERO;
                        yearSignAmountTotal = BigDecimal.ZERO;
                        beginningReceivable = earlyReceivableAmount;
                    }
                    //是否历史月
                    if(LocalDateTimeUtils.compareDate(returnPlanDetail.getReturnTime(),returnPlanVersion.getCreateTime(),0)){
                        //获取当月签约的房间id列表在小于等于当月实收的金额
                        BigDecimal incrementReturnAmountActual = returnSignDataBO.getZlReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //获取累计签约房间id列表在等于当月实收的金额
                        BigDecimal storeReturnAmountActual = returnSignDataBO.getClReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);

                        //实际数-增量回款(当月签约的房间在当月及以前月实收的金额)
                        returnPlanDetail.setIncrementReturnAmountActual(incrementReturnAmountActual);
                        //实际数-存量回款(当月之前签约的房间在当月实收的金额)
                        returnPlanDetail.setStoreReturnAmountActual(storeReturnAmountActual);
                        //期初应退回款数(当月及以前签约的房间中当月及以前实收大于当月及以前应收的金额合计)
                        returnPlanDetail.setRefundable(BigDecimal.ZERO);
                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(BigDecimal.ZERO);
                        //增量回款-本期回款数(历史月：实际数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountActual());
                        //存量回款-本期回款数(历史月：实际数-存量回款)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountActual());
                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                        //是否编制月
                    }else if(LocalDateTimeUtils.compareDate(returnPlanDetail.getReturnTime(),returnPlanVersion.getCreateTime(),2)){
                        //获取当月签约的房间id列表在小于等于当月实收的金额
                        BigDecimal incrementReturnAmountActual = returnSignDataBO.getZlReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //获取累计签约房间id列表在等于当月实收的金额
                        BigDecimal storeReturnAmountActual = returnSignDataBO.getClReceiptsMoneyByYearMonth(groupId,combinationProductCode,yearMonth);
                        //筛选指定合同id列表中当月及以前的实收大于当月及以前的应收的合同id列表,获取其中当月及以前的实收大于当月及以前的签约的金额合计
                        BigDecimal refundable = returnSignDataBO.getRefundable(groupId, combinationProductCode, yearMonth);

                        //当前月已签未回
                        currentMonthSignedUnrecovered = earlyReceivableAmount;

                        //将当前月月初应收计入当月签约上,用于当月及未来月的测算数计算
                        contractAmountMap.put(yearMonth,contractAmountMap.get(yearMonth).add(earlyReceivableAmount));
                        //第1个月回款系数
                        BigDecimal oneMonthCoefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(1);
                        //当月签约 + 期初应收 * 第1个月回款系数
                        BigDecimal incrementReturnAmountCalculate = contractAmountMap.get(yearMonth).multiply(oneMonthCoefficient).setScale(5, BigDecimal.ROUND_HALF_UP);
                        //签约应收回款（NOS专用）
                        returnPlanDetail.setSignReceivableAmount(currentMonthSignedUnrecovered.multiply(oneMonthCoefficient).setScale(5, BigDecimal.ROUND_HALF_UP));
                        //实际数-增量回款(当月签约的合同在当月及以前月实收的金额)
                        returnPlanDetail.setIncrementReturnAmountActual(incrementReturnAmountActual);
                        //实际数-存量回款(当月之前签约的合同在当月实收的金额)
                        returnPlanDetail.setStoreReturnAmountActual(storeReturnAmountActual);
                        //期初应退回款数(当月及以前签约的合同中当月及以前实收大于当月及以前应收的金额合计)
                        returnPlanDetail.setRefundable(refundable);
                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(BigDecimal.ZERO);
                        //增量回款-测算数((当月签约 + 期初应收) * 第1个月回款系数)
                        returnPlanDetail.setIncrementReturnAmountCalculate(incrementReturnAmountCalculate);
                        //存量回款-测算数(编制月为0)(从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和)
                        returnPlanDetail.setStoreReturnAmountCalculate(BigDecimal.ZERO);
                        //增量回款-本期回款数(当月：测算数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountCalculate());
                        //存量回款-本期回款数(当月：测算数-存量回款  + 上月应收未收 + 当月应收)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountCalculate()
                                .add(lastMonthNotReceivableAmount).add(returnPlanDetail.getReceivableAmount()));

                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                        //是否未来月
                    }else {
                        //签约应收回款(NOS专用)
                        getSignReceivableAmount(currentMonthSignedUnrecovered,returnPlanDetail,returnCoefficientMap);

                        //第1个月回款系数
                        BigDecimal oneMonthCoefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(1);
                        //当月签约 * 第1个月回款系数
                        BigDecimal incrementReturnAmountCalculate = returnPlanDetail.getPlanSignAmount().multiply(oneMonthCoefficient);
                        //从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和
                        BigDecimal storeReturnAmountCalculate = BigDecimal.ZERO;
                        for (LocalDateTime time = returnPlanVersion.getCreateTime(); LocalDateTimeUtils.compareDate(time, returnPlanDetail.getReturnTime(), 0); time = LocalDateTimeUtils.addDate(time)) {
                            //签约金额
                            BigDecimal contractAmount = contractAmountMap.get(LocalDateTimeUtils.formatTime(time, DateUtils.DATE_JFP_STR));
                            //月数
                            int monthCount = LocalDateTimeUtils.monthDiff(time, returnPlanDetail.getReturnTime()) + 1;
                            //回款系数
                            BigDecimal coefficient;
                            if(monthCount > 24){
                                //回款系数
                                coefficient = BigDecimal.ZERO;
                            }else {
                                //回款系数
                                coefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(monthCount);
                            }
                            //回款金额
                            BigDecimal returnAmount = contractAmount.multiply(coefficient);

                            storeReturnAmountCalculate = storeReturnAmountCalculate.add(returnAmount);
                        }

                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(BigDecimal.ZERO);
                        //增量回款-测算数((当月签约 + 期初应收) * 第1个月回款系数)
                        returnPlanDetail.setIncrementReturnAmountCalculate(incrementReturnAmountCalculate);
                        //存量回款-测算数(从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和)
                        returnPlanDetail.setStoreReturnAmountCalculate(storeReturnAmountCalculate);
                        //增量回款-本期回款数(未来月：测算数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountCalculate());
                        //存量回款-本期回款数(未来月：测算数-存量回款  +  上月应收未收 + 当月应收)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountCalculate()
                                .add(lastMonthNotReceivableAmount).add(returnPlanDetail.getReceivableAmount()));
                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                    }
                    //累计签约合计(历史月累加实际签约,的编制月及未来月累加计划签约)
                    signAmountTotal = signAmountTotal.add(returnPlanDetail.getSignAmount());
                    //累计年度签约合计(历史月累加实际签约,的编制月及未来月累加计划签约)
                    yearSignAmountTotal = yearSignAmountTotal.add(returnPlanDetail.getSignAmount());
                    //累计回款合计(累计回款合计 + 当月回款合计)
                    returnAmountTotal = returnAmountTotal.add(returnPlanDetail.getTotalReturnAmount());
                    //累计年度回款合计(累计年度回款合计 + 当月回款合计)
                    yearReturnAmountTotal = yearReturnAmountTotal.add(returnPlanDetail.getTotalReturnAmount());
                    //累计签约回款率(开售月累计到当月回款合计/开售月累计到累计当月签约金额)
                    BigDecimal signReturnRate = BigDecimalUtils.divBigDecimal(returnAmountTotal,signAmountTotal,5);
                    //年度综合回款率(从当年1月累计到当月回款合计/(当年1月的期初应收 + 从当年1月累计到累计当月签约金额)
                    BigDecimal annualOverallReturnRate = BigDecimalUtils
                            .divBigDecimal(yearReturnAmountTotal,beginningReceivable.add(yearSignAmountTotal),5);

                    returnPlanDetail.setYearReturnAmountTotal(yearReturnAmountTotal);
                    returnPlanDetail.setReturnAmountTotal(returnAmountTotal);
                    returnPlanDetail.setYearSignAmountTotal(yearSignAmountTotal);
                    returnPlanDetail.setSignAmountTotal(signAmountTotal);
                    returnPlanDetail.setSignReturnRate(signReturnRate);
                    returnPlanDetail.setAnnualOverallReturnRate(annualOverallReturnRate);
                }
            }
        }

    }

    /**
     * //签约应收回款（NOS专用）
     * @param currentMonthSignedUnrecovered 当前月已签未回
     * @param returnPlanDetail 回款详情
     * @param returnCoefficientMap 回款系数Map
     */
    private void getSignReceivableAmount(BigDecimal currentMonthSignedUnrecovered, ReturnPlanVersionDetail returnPlanDetail, Map<String, Map<Integer, BigDecimal>> returnCoefficientMap) {
        //月数
        int monthCount = LocalDateTimeUtils.monthDiff(returnPlanDetail.getCreateTime(), returnPlanDetail.getReturnTime()) + 1;
        //回款系数
        BigDecimal coefficient;
        if(monthCount > 24){
            coefficient = BigDecimal.ZERO;
        }else {
            coefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(monthCount);
        }
        //签约应收回款（NOS专用）
        returnPlanDetail.setSignReceivableAmount(currentMonthSignedUnrecovered.multiply(coefficient).setScale(5, BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 计算投资版回款计划详情数据
     * @param returnPlanVersion 回款计划版本
     * @param returnPlanVersionDetailList 回款计划详情列表
     */
    private void calculateListByInvestment(ReturnPlanVersion returnPlanVersion, List<ReturnPlanVersionDetail> returnPlanVersionDetailList) {
        //获取回款系数数据（计算当月及未来月数据使用）(key:标准业态编码，(key:月数，value:回款系数)
        Map<String,Map<Integer,BigDecimal>> returnCoefficientMap = getReturnCoefficientData(returnPlanVersion);

        //以组团id和组合业态分组，并已回款时间做升序排序,(key:组团ID，(key:组合业态编码，value:回款计划详情))
        Map<String, LinkedHashMap<String, List<ReturnPlanVersionDetail>>> returnPlanDetailByGroupIdMap = returnPlanVersionDetailList
                .stream().sorted(Comparator.comparing(ReturnPlanVersionDetail::getReturnTime))
                .collect(Collectors.groupingBy(ReturnPlanVersionDetail::getGroupId,
                        Collectors.groupingBy(ReturnPlanVersionDetail::getCombinationProductCode, LinkedHashMap::new, Collectors.toList())));

        for (String groupId : returnPlanDetailByGroupIdMap.keySet()) {
            LinkedHashMap<String, List<ReturnPlanVersionDetail>> returnPlanDetailMap = returnPlanDetailByGroupIdMap.get(groupId);
            for (String combinationProductCode : returnPlanDetailMap.keySet()) {
                //累计签约合同id列表
                List<String> cumulativeSignRoomIdList = new ArrayList();
                //上月应收未收
                BigDecimal lastMonthNotReceivableAmount = BigDecimal.ZERO;
                //应收未收
                BigDecimal notReceivableAmount = BigDecimal.ZERO;
                //期初应收
                BigDecimal earlyReceivableAmount = BigDecimal.ZERO;
                //累计回款合计
                BigDecimal returnAmountTotal = BigDecimal.ZERO;
                //累计年度签约合计
                BigDecimal yearSignAmountTotal = BigDecimal.ZERO;
                //累计年度回款合计
                BigDecimal yearReturnAmountTotal = BigDecimal.ZERO;
                //累计签约合计
                BigDecimal signAmountTotal = BigDecimal.ZERO;
                //1月期初应收
                BigDecimal beginningReceivable = BigDecimal.ZERO;

                List<ReturnPlanVersionDetail> returnPlanDetails = returnPlanDetailMap.get(combinationProductCode);
                //获取签约金额Map(key:年月,value:签约金额)
                Map<String, BigDecimal> contractAmountMap = returnPlanDetails.stream()
                        .collect(Collectors.toMap(s -> LocalDateTimeUtils.formatTime(s.getReturnTime(), DateUtils.DATE_JFP_STR), ReturnPlanVersionDetail::getSignAmount));
                for (ReturnPlanVersionDetail returnPlanDetail : returnPlanDetails){
                    String yearMonth =  LocalDateTimeUtils.formatTime(returnPlanDetail.getReturnTime(), DateUtils.DATE_JFP_STR);

                    //获取当月应收
                    BigDecimal receivableAmount = BigDecimal.ZERO;
                    //获取当月实收
                    BigDecimal receiptsAmount = BigDecimal.ZERO;
                    //应收未收
                    notReceivableAmount = receivableAmount.subtract(receiptsAmount);
                    //是否当年1月(重新计算累计年度回款合计、累计年度签约合计、1月期初应收)
                    if(returnPlanDetail.getReturnTime().getMonthValue() == 1){
                        yearReturnAmountTotal = BigDecimal.ZERO;
                        yearSignAmountTotal = BigDecimal.ZERO;
                        beginningReceivable = earlyReceivableAmount;
                    }
                    //是否历史月
                    if(LocalDateTimeUtils.compareDate(returnPlanDetail.getReturnTime(),returnPlanVersion.getCreateTime(),0)){
                        //实际数-增量回款(当月签约的合同在当月及以前月实收的金额)
                        returnPlanDetail.setIncrementReturnAmountActual(BigDecimal.ZERO);
                        //实际数-存量回款(当月之前签约的合同在当月实收的金额)
                        returnPlanDetail.setStoreReturnAmountActual(BigDecimal.ZERO);
                        //期初应退回款数(当月及以前签约的合同中当月及以前实收大于当月及以前应收的金额合计)
                        returnPlanDetail.setRefundable(BigDecimal.ZERO);
                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(receivableAmount);
                        //增量回款-本期回款数(历史月：实际数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountActual());
                        //存量回款-本期回款数(历史月：实际数-存量回款)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountActual());
                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                        //获取下个月的上月应收未收（应收未收）
                        lastMonthNotReceivableAmount = lastMonthNotReceivableAmount.add(notReceivableAmount);
                        //是否编制月
                    }else if(LocalDateTimeUtils.compareDate(returnPlanDetail.getReturnTime(),returnPlanVersion.getCreateTime(),2)){
                        //第1个月回款系数
                        BigDecimal oneMonthCoefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(1);
                        //当月签约 * 第1个月回款系数
                        BigDecimal incrementReturnAmountCalculate = returnPlanDetail.getPlanSignAmount().multiply(oneMonthCoefficient).setScale(5, BigDecimal.ROUND_HALF_UP);;
                        //实际数-增量回款(当月签约的合同在当月及以前月实收的金额)
                        returnPlanDetail.setIncrementReturnAmountActual(BigDecimal.ZERO);
                        //实际数-存量回款(当月之前签约的合同在当月实收的金额)
                        returnPlanDetail.setStoreReturnAmountActual(BigDecimal.ZERO);
                        //期初应退回款数(当月及以前签约的合同中当月及以前实收大于当月及以前应收的金额合计)
                        returnPlanDetail.setRefundable(BigDecimal.ZERO);
                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(receivableAmount);
                        //增量回款-测算数(当月签约 * 第1个月回款系数)
                        returnPlanDetail.setIncrementReturnAmountCalculate(incrementReturnAmountCalculate);
                        //存量回款-测算数(编制月为0)(从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和)
                        returnPlanDetail.setStoreReturnAmountCalculate(BigDecimal.ZERO);
                        //增量回款-本期回款数(当月：测算数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountCalculate());
                        //存量回款-本期回款数(当月：测算数-存量回款  + 上月应收未收 - 期初应退 + 当月应收)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountCalculate()
                                .add(lastMonthNotReceivableAmount).subtract(returnPlanDetail.getRefundable()).add(returnPlanDetail.getReceivableAmount()));

                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                        //获取下个月的上月应收未收（应收未收）
                        lastMonthNotReceivableAmount = BigDecimal.ZERO;

                        //是否未来月
                    }else {
                        //第1个月回款系数
                        BigDecimal oneMonthCoefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(1);
                        //当月签约 * 第1个月回款系数
                        BigDecimal incrementReturnAmountCalculate = returnPlanDetail.getPlanSignAmount().multiply(oneMonthCoefficient);
                        //从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和
                        BigDecimal storeReturnAmountCalculate = BigDecimal.ZERO;
                        for (LocalDateTime time = returnPlanVersion.getCreateTime(); LocalDateTimeUtils.compareDate(time, returnPlanDetail.getReturnTime(), 0); time = LocalDateTimeUtils.addDate(time)) {
                            //签约金额
                            BigDecimal contractAmount = contractAmountMap.get(LocalDateTimeUtils.formatTime(time, DateUtils.DATE_JFP_STR));
                            //月数
                            int monthCount = LocalDateTimeUtils.monthDiff(time, returnPlanDetail.getReturnTime()) + 1;
                            //回款系数
                            BigDecimal coefficient;
                            if(monthCount > 24){
                                //回款系数
                                coefficient = BigDecimal.ZERO;
                            }else {
                                //回款系数
                                coefficient = returnCoefficientMap.get(returnPlanDetail.getProProductCode()).get(monthCount);
                            }
                            //回款金额
                            BigDecimal returnAmount = contractAmount.multiply(coefficient);

                            storeReturnAmountCalculate = storeReturnAmountCalculate.add(returnAmount);
                        }

                        //供款计划数-存量回款	(当月应收)
                        returnPlanDetail.setReceivableAmount(receivableAmount);
                        //增量回款-测算数(当月签约 * 第1个月回款系数)
                        returnPlanDetail.setIncrementReturnAmountCalculate(incrementReturnAmountCalculate);
                        //存量回款-测算数(从编制月至当月中(各月的签约金额 * 第(编制月至各月的月数差+1)个月的回款系数)之和)
                        returnPlanDetail.setStoreReturnAmountCalculate(storeReturnAmountCalculate);

                        //增量回款-本期回款数(未来月：测算数-增量回款)
                        returnPlanDetail.setIncrementReturnAmount(returnPlanDetail.getIncrementReturnAmountCalculate());
                        //存量回款-本期回款数(未来月：测算数-存量回款  +  上月应收未收 + 当月应收)
                        returnPlanDetail.setStoreReturnAmount(returnPlanDetail.getStoreReturnAmountCalculate()
                                .add(lastMonthNotReceivableAmount).add(returnPlanDetail.getReceivableAmount()));

                        //回款合计-本期回款数(增量回款 + 存量回款)
                        returnPlanDetail.setTotalReturnAmount(returnPlanDetail.getIncrementReturnAmount().add(returnPlanDetail.getStoreReturnAmount()));
                        //期初应收
                        returnPlanDetail.setEarlyReceivableAmount(earlyReceivableAmount);
                        //上月应收未收
                        returnPlanDetail.setLastMonthNotReceivableAmount(lastMonthNotReceivableAmount);
                        //期末应收(期初应收 + 编制月月度签约 - 编制月回款合计)
                        returnPlanDetail.setFinalReceivable(earlyReceivableAmount.add(returnPlanDetail.getSignAmount()).subtract(returnPlanDetail.getTotalReturnAmount()));
                        //已签未回数(期末应收)
                        returnPlanDetail.setSignedUnrecovered(returnPlanDetail.getFinalReceivable());

                        //获取下个月的期初应收(期末应收)
                        earlyReceivableAmount = returnPlanDetail.getFinalReceivable();
                    }
                    //累计签约合计(历史月累加实际签约,的编制月及未来月累加计划签约)
                    signAmountTotal = signAmountTotal.add(returnPlanDetail.getSignAmount());
                    //累计年度签约合计(历史月累加实际签约,的编制月及未来月累加计划签约)
                    yearSignAmountTotal = yearSignAmountTotal.add(returnPlanDetail.getSignAmount());
                    //累计回款合计(累计回款合计 + 当月回款合计)
                    returnAmountTotal = returnAmountTotal.add(returnPlanDetail.getTotalReturnAmount());
                    //累计年度回款合计(累计年度回款合计 + 当月回款合计)
                    yearReturnAmountTotal = yearReturnAmountTotal.add(returnPlanDetail.getTotalReturnAmount());
                    //累计签约回款率(开售月累计到当月回款合计/开售月累计到累计当月签约金额)
                    BigDecimal signReturnRate = BigDecimalUtils.divBigDecimal(returnAmountTotal,signAmountTotal,4);
                    //年度综合回款率(从当年1月累计到当月回款合计/(当年1月的期初应收 + 从当年1月累计到累计当月签约金额)
                    BigDecimal annualOverallReturnRate = BigDecimalUtils
                            .divBigDecimal(yearReturnAmountTotal,beginningReceivable.add(yearSignAmountTotal),4);

                    returnPlanDetail.setYearReturnAmountTotal(yearReturnAmountTotal);
                    returnPlanDetail.setReturnAmountTotal(returnAmountTotal);
                    returnPlanDetail.setYearSignAmountTotal(yearSignAmountTotal);
                    returnPlanDetail.setSignAmountTotal(signAmountTotal);
                    returnPlanDetail.setSignReturnRate(signReturnRate);
                    returnPlanDetail.setAnnualOverallReturnRate(annualOverallReturnRate);
                }
            }
        }
    }

    /**
     * 获取回款NOS签约数据
     * @param returnPlanVersion
     * @return
     */
    private ReturnPlanNosSaleDataBO getReturnNosSignData(ReturnPlanVersion returnPlanVersion) {
        ReturnPlanNosSaleDataBO returnSignDataBO = new ReturnPlanNosSaleDataBO();
        //产品构成层级供货详情列表
        List<SignPlanVersionSupplyDetail> supplyDetailList = signPlanVersionSupplyDetailMapper.selectByVersionIds(Arrays.asList(returnPlanVersion.getSignPlanVersionId()), IsDeleteEnum.NO.getKey());
        //获取组团idMap(key:供货id,value:组团id)
        Map<String, String> groupIdMap = supplyDetailList.stream()
                .filter(s -> OrgTypeEunm.ORG_GROUP.getKey().equals(s.getType()))
                .collect(Collectors.toMap(SignPlanVersionSupplyDetail::getSupplyPlanId, SignPlanVersionSupplyDetail::getOrgId));
        //获取组团idMap(key:楼栋id,value:组团id)
        Map<String, String> groupIdByBuildingMap = supplyDetailList.stream()
                .filter(s -> OrgTypeEunm.ORG_PRODUCT.getKey().equals(s.getType()))
                .collect(Collectors.toMap(SignPlanVersionSupplyDetail::getOrgId, s -> groupIdMap.get(s.getPid())));
        //获取楼栋id与组合业态关系Map(key:楼栋id,value:组合业态)
        Map<String,String> buildingMap = supplyDetailList.stream()
                .filter(s -> OrgTypeEunm.ORG_PRODUCT.getKey().equals(s.getType()) && StringUtils.isNotBlank(s.getOrgId()))
                .collect(Collectors.toMap(SignPlanVersionSupplyDetail::getOrgId,s -> s.getOrgCode() +s.getFreeType() +s.getBusinessType() +s.getProType()));

        List<String> buildingList = new ArrayList<>(buildingMap.keySet());

        if(CollectionUtils.isEmpty(buildingList)){
            return returnSignDataBO;
        }

        //签约记录(签约合同记录表)
        List<NosTradedataDto> nosTradedataDtoList = dmOdsNosTradedataviewformarsService.selectNosContractList(new ArrayList<>(buildingMap.keySet()));
        //实收
        List<VsNosGetin> vsNosGetinList = vsNosPayabledataviewformarsService.selectByStageIdList(returnPlanVersion.getStageId());

        //签约记录列表
        List<ReturnSignRecordsDto> returnSignRecordsList = nosTradedataDtoList.stream()
                .filter(s->LocalDateTimeUtils.compareDate(s.getTradeDate(),LocalDateTime.now(),0)).map(s->{
            return new ReturnSignRecordsDto(
                    groupIdByBuildingMap.get(s.getBuildingId()),
                    buildingMap.get(s.getBuildingId()),
                    LocalDateTimeUtils.formatTime(s.getTradeDate(), DateUtils.DATE_JFP_STR),
                    s.getRoomId(),s.getTradeMoney());
        }).collect(Collectors.toList());
        //实收列表
        List<ReturnSignNosReceiptsDto> returnSignReceiptsList = vsNosGetinList.stream().map(s->{
            return new ReturnSignNosReceiptsDto(
                    groupIdByBuildingMap.get(s.getBuildingId()),
                    LocalDateTimeUtils.formatTime(s.getPayableDate(), DateUtils.DATE_JFP_STR),
                    s.getRoomId(),
                    s.getPayableMoney(),
                    s.getDataType());
        }).collect(Collectors.toList());

        returnSignDataBO.setReturnSignRecordsList(returnSignRecordsList);
        returnSignDataBO.setReturnSignReceiptsList(returnSignReceiptsList);

        returnSignDataBO.initializeMap();
        return returnSignDataBO;
    }

    /**
     * 获取回款系数数据(key:标准业态编码，(key:月数，value:回款系数)
     * @param returnPlanVersion 回款计划版本
     * @return
     */
    private Map<String, Map<Integer, BigDecimal>> getReturnCoefficientData(ReturnPlanVersion returnPlanVersion) {
        List<ReturnCoefficientDetail> returnCoefficientDetailList = returnPlanVersionCoefficientService.getReturnCoefficientDetailListByReturnPlanVersionId(returnPlanVersion.getId());

        //回款系数详情列表转Map（key:版本类型编码，value:项目回款系数）
        Map<String, Map<Integer, BigDecimal>> returnCoefficientByProProductCodeMap = returnCoefficientDetailList.stream().collect(Collectors.toMap(ReturnCoefficientDetail::getProProductCode, s -> {
            Map<Integer, BigDecimal> map = new HashMap<>();
            map.put(1, s.getOneMonth());
            map.put(2, s.getTwoMonth());
            map.put(3, s.getThreeMonth());
            map.put(4, s.getFourMonth());
            map.put(5, s.getFiveMonth());
            map.put(6, s.getSixMonth());
            map.put(7, s.getSevenMonth());
            map.put(8, s.getEightMonth());
            map.put(9, s.getNineMonth());
            map.put(10, s.getTenMonth());
            map.put(11, s.getElevenMonth());
            map.put(12, s.getTwelveMonth());
            map.put(13, s.getThirteenMonth());
            map.put(14, s.getFourteenMonth());
            map.put(15, s.getFifteenMonth());
            map.put(16, s.getSixteenMonth());
            map.put(17, s.getSeventeenMonth());
            map.put(18, s.getEighteenMonth());
            map.put(19, s.getNineteenMonth());
            map.put(20, s.getTwentyMonth());
            map.put(21, s.getTwentyOneMonth());
            map.put(22, s.getTwentyTwoMonth());
            map.put(23, s.getTwentyThreeMonth());
            map.put(24, s.getTwentyFourMonth());
            return map;
        }));
        return returnCoefficientByProProductCodeMap;
    }

    /**
     * 初始化生成回款计划详情列表
     * @param returnPlanVersion 回款计划版本
     * @param returnPlanSaleDataBO
     * @return
     */
    private List<ReturnPlanVersionDetail> initializeList(ReturnPlanVersion returnPlanVersion, ReturnPlanSaleDataBO returnPlanSaleDataBO) {
        //获取签约计划详情列表
        List<SignPlanVersionDetail> signPlanVersionDetailList = signPlanVersionDetailMapper.selectByVersionId(returnPlanVersion.getSignPlanVersionId(), IsDeleteEnum.NO.getKey());

        List<ReturnPlanVersionDetail> returnPlanVersionDetailList = new ArrayList<>();

        //获取每个组团下最早签约时间
        Map<String, LocalDateTime> signPlanTimeByGroupIdMap = signPlanVersionDetailList.stream()
                .collect(Collectors.toMap(SignPlanVersionDetail::getGroupId, SignPlanVersionDetail::getSignPlanTime,
                        (c1, c2) -> (c1.compareTo(c2) <= 0 ? c1 : c2).compareTo(LocalDateTime.now()) <= 0 ? (c1.compareTo(c2) <= 0 ? c1 : c2) : LocalDateTime.now( )));

        //以组团id和组合业态分组，并已回款时间做升序排序,(key:组团ID，(key:组合业态编码，value:回款计划详情))
        Map<String, LinkedHashMap<String, List<SignPlanVersionDetail>>> signPlanDetailByGroupIdMap = signPlanVersionDetailList
                .stream().sorted(Comparator.comparing(SignPlanVersionDetail::getSignPlanTime))
                .collect(Collectors.groupingBy(SignPlanVersionDetail::getGroupId,
                        Collectors.groupingBy(s -> s.getProductCode() + s.getFreeType() + s.getBusinessType() + s.getProType(), LinkedHashMap::new, Collectors.toList())));

        for (String groupId : signPlanDetailByGroupIdMap.keySet()) {
            LinkedHashMap<String, List<SignPlanVersionDetail>> signPlanDetailMap = signPlanDetailByGroupIdMap.get(groupId);
            //获取该组团下最早签约时间
            LocalDateTime earlyDateTime = signPlanTimeByGroupIdMap.get(groupId);

            for (String combinationProductCode : signPlanDetailMap.keySet()) {
                List<SignPlanVersionDetail> signPlanDetails = signPlanDetailMap.get(combinationProductCode);

                Map<String, SignPlanVersionDetail> signPlanDetailMapByYearMonth = signPlanDetails.stream().collect(Collectors.toMap(s -> LocalDateTimeUtils.formatTime(s.getSignPlanTime(), DateUtils.DATE_JFP_STR), s -> s));

                SignPlanVersionDetail signPlanDetail = signPlanDetails.get(0);

                //将签约最晚数据加两年数据与最晚应收时间对比，计算回款最晚时间
                LocalDateTime lastDateTime = signPlanDetails.get(signPlanDetails.size()-1).getSignPlanTime();
                if(LocalDateTimeUtils.compareDate(lastDateTime,LocalDateTime.now(),1)){
                    lastDateTime = LocalDateTime.now().plusMonths(24);
                }else {
                    lastDateTime = lastDateTime.plusMonths(24);
                }
                LocalDateTime lastReceivableTime = returnPlanSaleDataBO.getLastReceivableTime(groupId, combinationProductCode);
                if(null != lastReceivableTime){
                    if(LocalDateTimeUtils.compareDate(lastDateTime,lastReceivableTime,1)){
                        lastDateTime = lastReceivableTime;
                    }
                }

                for (LocalDateTime dateTime = earlyDateTime; dateTime.compareTo(lastDateTime) <= 0  ; dateTime = dateTime.plusMonths(1)) {
                    String yearMonth = LocalDateTimeUtils.formatTime(dateTime, DateUtils.DATE_JFP_STR);

                    ReturnPlanVersionDetail returnPlanVersionDetail = new ReturnPlanVersionDetail();

                    //字段拷贝
                    BeanUtils.copyProperties(signPlanDetail,returnPlanVersionDetail);
                    returnPlanVersionDetail.setId(UUIDUtils.create());
                    returnPlanVersionDetail.setVersionId(returnPlanVersion.getId());
                    returnPlanVersionDetail.setCombinationProductCode(signPlanDetail.getProductCode()+signPlanDetail.getFreeType()+signPlanDetail.getBusinessType()+signPlanDetail.getProType());
                    returnPlanVersionDetail.setCombinationProductName(signPlanDetail.getProductName()+signPlanDetail.getFreeTypeName()+signPlanDetail.getBusinessTypeName()+signPlanDetail.getProTypeName());

                    returnPlanVersionDetail.setIsAllowedDelete(WhetherEnum.NO.getKey());
                    returnPlanVersionDetail.initialize(dateTime,signPlanDetail.getCreateBy());

                    SignPlanVersionDetail detail = signPlanDetailMapByYearMonth.get(yearMonth);
                    if(null != detail){
                        returnPlanVersionDetail.setActualSignAmount(detail.getEarlySignSumPriceActual().add(detail.getSupplySignSumPriceActual()));
                        returnPlanVersionDetail.setPlanSignAmount(detail.getEarlySignSumPrice().add(detail.getSupplySignSumPrice()));
                        if(LocalDateTimeUtils.compareDate(detail.getSignPlanTime(),returnPlanVersion.getCreateTime(),0)){
                            returnPlanVersionDetail.setSignAmount(returnPlanVersionDetail.getActualSignAmount());
                        }else {
                            returnPlanVersionDetail.setSignAmount(returnPlanVersionDetail.getPlanSignAmount());
                        }
                    }
                    returnPlanVersionDetailList.add(returnPlanVersionDetail);
                }

            }
        }


        return returnPlanVersionDetailList;
    }
}
